#include "ObjReader.h"

MeshPtr ObjReader::ReadMesh(const std::string& path, bool exitOnFail)
{
	MeshPtr mesh = std::make_unique<Mesh>();
	Mesh& meshRef = *mesh;

	meshRef.request_face_normals();
	meshRef.request_vertex_normals();
	meshRef.request_vertex_texcoords2D();

	// 读取顶点法向、面法向和顶点纹理坐标
	OpenMesh::IO::Options opts;
	opts += OpenMesh::IO::Options::VertexNormal;
	opts += OpenMesh::IO::Options::FaceNormal;
	opts += OpenMesh::IO::Options::VertexTexCoord;

	if (!OpenMesh::IO::read_mesh(meshRef, path, opts))
	{
		std::cerr << "Failed to read mesh at [" << path << "]" << std::endl;

		if (exitOnFail)
			exit(1);

		return nullptr;
	}

	meshRef.update_face_normals();
	meshRef.update_vertex_normals();

	return mesh;
}

GLMeshPtr ObjReader::AsGLMesh(const MeshPtr& mesh)
{
	std::vector<GLVertex> vertices;
	std::vector<unsigned int> indices;

	std::cout << std::distance(mesh->vertices_begin(), mesh->vertices_end()) << std::endl;

	for (auto it = mesh->faces_begin(); it != mesh->faces_end(); ++it)
	{
		auto& face = *it;

		// 遍历面上的顶点
		auto fv_iter = mesh->fv_begin(face), fv_end = mesh->fv_end(face);
		for (; fv_iter != fv_end; fv_iter++)
		{
			// 获得顶点位置和法向
			const auto& p = mesh->point(*fv_iter);
			const auto& n = mesh->normal(*fv_iter);
			const auto& t = mesh->texcoord2D(*fv_iter);

			GLVertex vertex;
			vertex.position = { p[0], p[1], p[2] };
			vertex.normal = { n[0], n[1], n[2] };
			vertex.texCoords = { t[0], t[1] };

			vertices.push_back(vertex);
			indices.push_back(indices.size());
		}
	}

	return GLMeshPtr(new GLMesh(vertices, indices));
}

GLMeshPtr ObjReader::AsGLMesh(const MeshPtr& mesh, FaceList& fList, Mesh::TexCoord2D tex)
{
	std::vector<GLVertex> vertices;
	std::vector<unsigned int> indices;

	for (auto& face : fList)
	{
		// 遍历面上的顶点
		auto fv_iter = mesh->fv_begin(face), fv_end = mesh->fv_end(face);
		for (; fv_iter != fv_end; fv_iter++)
		{
			// 获得顶点位置和法向
			const auto& p = mesh->point(*fv_iter);
			const auto& n = mesh->normal(*fv_iter);

			GLVertex vertex;
			vertex.position = { p[0], p[1], p[2] };
			vertex.normal = { n[0], n[1], n[2] };
			vertex.texCoords = { tex[0], tex[1] };

			vertices.push_back(vertex);
			indices.push_back(indices.size());
		}
	}

	return GLMeshPtr(new GLMesh(vertices, indices));
}

GLMeshPtr ObjReader::AsParaGLMesh(const MeshPtr& mesh)
{
	std::vector<GLVertex> vertices;
	std::vector<unsigned int> indices;

	std::cout << std::distance(mesh->vertices_begin(), mesh->vertices_end()) << std::endl;

	for (auto it = mesh->faces_begin(); it != mesh->faces_end(); ++it)
	{
		auto& face = *it;

		// 遍历面上的顶点
		auto fv_iter = mesh->fv_begin(face), fv_end = mesh->fv_end(face);
		for (; fv_iter != fv_end; fv_iter++)
		{
			// 获得参数
			const auto& t = mesh->texcoord2D(*fv_iter);

			GLVertex vertex;
			vertex.position = { t[0], 0, t[1] };
			vertex.normal = { 0, 1, 0 };
			vertex.texCoords = { t[0], t[1] };

			vertices.push_back(vertex);
			indices.push_back(indices.size());
		}
	}

	return GLMeshPtr(new GLMesh(vertices, indices));
}
